﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SharingCenter.Web.Classes.Groups
{
    using SharingCenter.Web.Classes;
    using SharingCenter.Web.Classes.enums;
    using SharingCenter.Web.Classes.Messages;
    using System.Xml.Linq;
    using SharingCenter.Web.Classes.SiteEvents;
    public static class GroupOperations
    {

        public static List<Sc_GroupMember> GetGroupAdminList(Guid groupId)
        {
            using (scDataContext c = new scDataContext())
            {
                var admins = from t in c.Sc_GroupMembers
                             where t.GroupId == groupId && t.AdminRole != SharingCenter.Web.Classes.enums.GroupRole.NA
                             select t;
                return admins.ToList();
            }
        }

        public static void AddSiteEventOnNewMember(Guid groupId, Guid userId)
        {
            XElement cxt = new XElement("Event",
                new XElement("GroupId", groupId),
                new XElement("UserId", userId),
                new XElement("JoinDate", DateTime.Now));
            SiteEventOperations.AddEvent("Groups", "NewMember", "Groups", userId, cxt, true, groupId);
        }

        public static void AddUserToGroup(Guid userId, Guid groupId, bool submitChanges)
        {
            if (!GroupMemberExists(userId, groupId))
            {
                Sc_GroupMember g = new Sc_GroupMember();
                g.GroupId = groupId;
                g.UserId = userId;
                g.JoinDate = DateTime.Now;
                g.DisplayInfo = null;
                g.Comment = "";
                g.AdminRole = GroupRole.NA;

                

                Sc_Group group = GroupOperations.GetGroupByGroupId(groupId);

                XElement context = new XElement("Context",
                    new XAttribute("XsltFolderInMod", "Groups"),
                    new XElement("Event",
                        new XAttribute("Name", "GroupApproved"),
                        new XElement("GroupId", groupId),
                        new XElement("GroupName", group.GroupName)));

                MessageOperations.SendSystemMessage(userId, userId, "GroupApproved", context, true);

                using (scDataContext c = new scDataContext())
                {
                    c.Sc_GroupMembers.InsertOnSubmit(g);

                    if (submitChanges)
                    {
                        c.SubmitChanges(System.Data.Linq.ConflictMode.FailOnFirstConflict);
                    }
                }
            }
        }

        public static void AddUserToGroup(Guid userId, Guid groupId, GroupRole groupRole, bool submitChanges)
        {
            if (!GroupMemberExists(userId, groupId))
            {
                Sc_GroupMember g = new Sc_GroupMember();
                g.GroupId = groupId;
                g.UserId = userId;
                g.JoinDate = DateTime.Now;
                g.DisplayInfo = null;
                g.Comment = "";
                g.AdminRole = groupRole;

                using (scDataContext c = new scDataContext())
                {
                    c.Sc_GroupMembers.InsertOnSubmit(g);

                    if (submitChanges)
                    {
                        c.SubmitChanges();
                    }
                }
            }
        }

        public static bool GroupMemberExists(Guid userId, Guid groupId)
        {
            bool exists = false;
            using (scDataContext con = new scDataContext())
            {
                try
                {
                    var q = from t in con.Sc_GroupMembers
                            where t.GroupId == groupId && t.UserId == userId
                            select t;
                    if(q.Count()>0)
                        exists = true;
                }
                catch { }
            }
            return exists;
        }

        public static Sc_Group GetGroupByGroupId(Guid groupId, out scDataContext dc)
        {
            scDataContext c = new scDataContext();
            dc = c;
            try
            {
                return c.Sc_Groups.Single(d => d.GroupId == groupId);
            }
            catch { return null; }
        }

        public static Sc_Group GetGroupByGroupId(Guid groupId)
        {
            using (scDataContext c = new scDataContext())
            {
                try
                {
                    return c.Sc_Groups.Single(d => d.GroupId == groupId);
                }
                catch { return null; }
            }
        }

        public static void RemoveUserFromGroup(Guid groupId, Guid userId)
        {
            using (scDataContext c = new scDataContext())
            {
                c.RemoveUserFromGroup(userId, groupId);
            }
        }

        public static List<Guid> GetGroupAdminUserList(Guid groupId)
        {
            using (scDataContext c = new scDataContext())
            {
                var q = from t in c.Sc_GroupMembers
                        where (t.AdminRole == GroupRole.GroupAdmin || t.AdminRole == GroupRole.Owner) && t.GroupId == groupId
                        select t.UserId;
                return q.ToList();
            }
        }

        public static void ChangeAdminRole(Guid groupId, Guid userId, GroupRole role)
        {
            using (scDataContext c = new scDataContext())
            {
                c.ChangeGroupRole(groupId, userId, (int)role);
            }
        }


        /// <summary>
        /// Return group member with group role or null if not found
        /// </summary>
        /// <param name="groupId">group id</param>
        /// <param name="userId">user id</param>
        /// <returns></returns>
        public static Sc_GroupMember GetGroupMember(Guid groupId, Guid userId)
        {
            try
            {
                using (scDataContext c = new scDataContext())
                {
                    return c.Sc_GroupMembers.Single(d => (d.UserId == userId && d.GroupId == groupId));
                }
            }
            catch { return null; }
        }

        public static List<Sc_Group> GetGroupsByUserId(Guid userId)
        {
            using (scDataContext c = new scDataContext())
            {
                var q = from t in c.Sc_GroupMembers
                        join g in c.Sc_Groups
                        on t.GroupId equals g.GroupId
                        where t.UserId == userId
                        select g;
                return q.ToList();
            }
        }

        public static List<Sc_Group> GetGroupsByUserId(Guid userId, bool showPublicGroupsOnly)
        {
            using (scDataContext c = new scDataContext())
            {
                var q = from t in c.Sc_GroupMembers
                        join g in c.Sc_Groups
                        on t.GroupId equals g.GroupId
                        where t.UserId == userId && (showPublicGroupsOnly ? (g.Privacy == (int)JoinGroupPrivacy.Public || g.Privacy == (int)JoinGroupPrivacy.AdminApproval) : 1 == 1)
                        && g.Approved
                        select g;
                return q.ToList();
            }
        }

        public static List<Sc_Group> GetNewGroups(int count)
        {
            using (scDataContext cxt = new scDataContext())
            {
                var q = (from t in cxt.Sc_Groups
                         where t.Privacy != (int)JoinGroupPrivacy.None && t.Approved
                         orderby t.CreateDate descending
                             select t
                             ).Take(count);
                return q.ToList();
                
            }
        }

        public static List<Sc_Group> GetHotGroups(int count)
        {
            using (scDataContext cxt = new scDataContext())
            {
                try
                {
                    var q = (from t in cxt.Sc_Groups
                             where t.Privacy != (int)JoinGroupPrivacy.None && t.Approved
                             orderby t.MemberCount descending, t.CreateDate descending
                             select t).Take(count);
                    return q.ToList();
                }
                catch { return null; }
            }
        }

        public static bool IsUserInGroupRole(Guid groupId, Guid userId, GroupRole role)
        {
            using (scDataContext cxt = new scDataContext())
            {
                return Convert.ToBoolean(cxt.IsUserInGroupRole(groupId, userId, (int)role));
            }
        }

        public static Guid GetGroupThreadCategoryId(Guid groupId)
        {
            using (scDataContext cxt = new scDataContext())
            {
                try
                {
                    return cxt.Sc_PostCategories.Single(d => (d.ContextType == EntityType.Group && d.ContextId == groupId)).PostCategoryId;
                }
                catch { return Guid.Empty; }
            }
        }

        public static void EnableGroup(Guid groupId, bool enabled)
        {
            scDataContext cxt;
            Sc_Group g = GetGroupByGroupId(groupId, out cxt);
            if (null != g)
            {
                if (g.Approved != enabled)
                {
                    g.Approved = enabled;
                }

                cxt.SubmitChanges();
            }
            cxt = null;
        }
    }
}
